package org.jeecg.modules.payment.strategy.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.JacksonUtil;
import org.jeecg.modules.payment.bo.PaymentParams;
import org.jeecg.modules.payment.bo.RefundParams;
import org.jeecg.modules.payment.bo.WechatPayChannel;
import org.jeecg.modules.payment.strategy.IPaymentService;
import org.jeecg.modules.payment.util.WechatChannelUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;

/**
 * @Description: 支付记录
 * @Author: sean
 * @Date:   2024-08-28
 * @Version: V1.0
 */
@Slf4j
public class WechatPaymentService implements IPaymentService {
    private WechatPayChannel payChannel;

    public WechatPaymentService(String payConfig) {
        this.payChannel = JacksonUtil.toJavaObject(payConfig,  WechatPayChannel.class);
    }

    @Override
    public JsonNode payment(PaymentParams params) throws JeecgBootException {
        String notifyUrl = PAYMENT_NOTIFY_URL
                + "/" + params.getBizType()
                + "/" + params.getPayChannel()
                + "/" + params.getPayWay()
                + "/" + TenantContext.getTenant();
        log.info("支付回调接口-------------:{}", notifyUrl);
        params.setPaymentNotifyUrl(notifyUrl);
        String bodyAsString = WechatChannelUtil.payment(params, this.payChannel);
        ObjectNode jsonNode = WechatChannelUtil.createSignature(bodyAsString, this.payChannel);
        jsonNode.put("tradeNo", params.getTradeNo());
        return jsonNode;
    }

    @Override
    public JsonNode payCallBack(HttpServletRequest request, String payWay, String tenantId) throws JeecgBootException {
        ObjectNode params = JacksonUtil.newJSONObject();
        // 获取请求头
        String wechatPayTimestamp = request.getHeader("Wechatpay-Timestamp");   // 时间戳
        String wechatPayNonce = request.getHeader("Wechatpay-Nonce");   // 随机字符串
        String wechatPaySignature = request.getHeader("Wechatpay-Signature");   // 应答签名
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");   // 序列号
        // 给微信服务器返回的值
        StringBuilder message = new StringBuilder();    // 请求报文

        StringBuffer builder = new StringBuffer();
        try (BufferedReader br = request.getReader()) {
            String str;
            while ((str = br.readLine()) != null) {
                builder.append(str);
            }
        } catch (IOException e) {
            //e.printStackTrace();
            log.error(e.getMessage());
            throw new JeecgBootException("解析请求信息是失败");
        }
        // 构建报文
        message.append(wechatPayTimestamp).append("\n");
        message.append(wechatPayNonce).append("\n");
        message.append(builder).append("\n");

        Boolean verifyResult = WechatChannelUtil.signVerify(wechatPaySerial, message.toString(), wechatPaySignature, this.payChannel);
        if(!verifyResult){
            log.error("签名错误");
            throw new JeecgBootException("签名错误");
        }
        log.info("step_2:验证签名通过");
        // 解密
        log.info("密文输出："+builder.toString());
        String decryptResult = WechatChannelUtil.decryptSign(builder.toString(), this.payChannel);
        log.info("解密结果："+decryptResult);
        if (StringUtils.isEmpty(decryptResult)) {
            log.error("解密失败");
            throw new JeecgBootException("解密失败");
        }
        log.info("step_3:解密通过");
        // 业务开始
        JSONObject jsonObj = JSON.parseObject(decryptResult);
        log.info("解释支付结果------------:{}", decryptResult);
        String tradeCode = jsonObj.getString("out_trade_no");
        String transactionId = jsonObj.getString("transaction_id");
        JSONObject amount = jsonObj.getJSONObject("amount");
        Long chargeAmount = amount.getLong("total");
//        JSONObject payer = jsonObj.getJSONObject("payer");
//        String openId = payer.getString("openid");
        params.put("payCode", tradeCode)
                .put("returnCode", "0")
                .put("otherCode", transactionId)
                .put("payAmount", BigDecimal.valueOf(chargeAmount).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP));
        return params;
    }

    @Override
    public JsonNode refund(RefundParams params) throws JeecgBootException {
        String json = WechatChannelUtil.refund(params, this.payChannel);
        return JacksonUtil.toJSON(json);
    }

    @Override
    public ObjectNode refundCallBack(JsonNode params) throws JeecgBootException {
        return null;
    }

    @Override
    public void callbackResponse(HttpServletResponse response, JsonNode params, boolean result){
        String results =  WechatChannelUtil.notifyStr(result);
        response.setContentType("application/json; charset=utf-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.write(results);
        } catch (Exception e) {
            log.error("微信支付回调处理失败,请检查原因!!!,{}", e.getMessage());
        } finally {
            out.flush();
            out.close();
        }
    }
}
